package rsvp.original_translation_combine;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import rsvp.Main_RSVP;
import rsvp.util.FileUtility;
import rsvp.util.PathToApplicationRoot;

import com.google.api.translate.Language;
import com.google.api.translate.Translate;

/**
 * Model a sentence in a longer text with paragraphs 
 * 
 * @author ksz
 */
public class Sentence
{
	public static final String PARAGRAPH_MARKER = "{{P}}";
	public static final String SENTENCE_MARKER = "\n{{S}}";
	
	private final static File fRoot = PathToApplicationRoot.getApplicationRootDirectory();
	public final static File TEST_PATH_ORIGINAL_FILE = new File(fRoot,  "./test/test_combineOriginalWithTranslation/text_o.txt");
	public final static File TEST_PATH_TRANSLATION_FILE = new File(fRoot, "./test/test_combineOriginalWithTranslation/text_t.txt");
	public final static File TEST_PATH_COMBINED_FILE = new File(fRoot, "./test/test_combineOriginalWithTranslation/text_C.txt");

	/**
	 * if this is translation then this variable should be set to false
	 */
	boolean isTranslation = false;
	
	/**
	 * Get paragraph location
	 */
	int iParagraph = 0;
	
	/**
	 * Get line in paragraph location
	 */
	int iLineInParagraph = 0;
	
	String sSentenceValue;
	String sNextSentenceType;
	
	/**
	 * this should help determine what is the current type 
	 */
	Sentence prev = null;

	
	/**
	 * @param sFoundText text to be added 
	 * @param prevSentence link to the previous sentence
	 * @param iParagraph2	paragraph location information
	 * @param iLineInParagraph2 line in paragraph information
	 * @param isTranslation2 
	 */
	public Sentence(String sFoundText, Sentence prevSentence, int iParagraph2, int iLineInParagraph2, boolean isTranslation2)
	{
		sNextSentenceType = sFoundText.endsWith(SENTENCE_MARKER) ? SENTENCE_MARKER : PARAGRAPH_MARKER;
		sSentenceValue = sFoundText.substring(0, sFoundText.length() - sNextSentenceType.length()).trim();
		prev = prevSentence;
		iParagraph = iParagraph2;
		iLineInParagraph = iLineInParagraph2;
		isTranslation = isTranslation2;

	}
	
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer("Next is: " + sNextSentenceType.trim());
		sb.append(" ");
		sb.append(!isTranslation ? "O":"T");
		sb.append(" " + iParagraph + "-" + iLineInParagraph);
		sb.append(" sSentence: " + sSentenceValue);
		
		return sb.toString();
	}
	
	/**
	 * @param sOriginal
	 * 
	 * @return
	 */
	public static ArrayList<Sentence> extractSentences(String sOriginal, boolean isTranslation)
	{
		String sMarkedText = mark(sOriginal);
//		System.out.println("sMarkedText = " + sMarkedText);
		ArrayList<Sentence> a = new ArrayList<Sentence>();
		
		// walk through the text search for sentence end
		int iPosNow = 0;
		int iParagraph = 1;
		int iLineInParagraph = 1;
		
		Sentence prev = null;
		do {
			int iNextPos = getNextPositionSentenceEnd(sMarkedText, iPosNow);
			if (iNextPos > -1)
			{
				final String sFoundText = sMarkedText.substring(iPosNow, iNextPos);
	
				Sentence s = new Sentence(sFoundText, prev, iParagraph, iLineInParagraph, isTranslation);
				a.add(s);
				iParagraph = s.getLocation_nextParagraph();
				iLineInParagraph = s.getLocation_nextLineInParagraph();
				
				prev = s;
			}
			iPosNow = iNextPos;
		}
		while(iPosNow > -1);
		
		
		return a;
	}

	/**
	 * 
	 */
	public boolean isThisSentenceStartingAParagraph() {
		if (prev == null)
			return true;
		
		return prev.sNextSentenceType.equals(PARAGRAPH_MARKER);
	}

	/**
	 * 
	 */
	public boolean isNextSentenceStartingAParagraph() {		
		return sNextSentenceType.equals(PARAGRAPH_MARKER);
	}

	/**
	 * @return
	 */
	private int getLocation_nextLineInParagraph()
	{
		if (isNextSentenceStartingAParagraph())
			return 1;
		else
			return iLineInParagraph+1;
	}

	/**
	 * @return
	 */
	private int getLocation_nextParagraph()
	{
		if (isNextSentenceStartingAParagraph())
			return iParagraph+1;
		else
			return iParagraph;
	}

	/**
	 * look for end of sequence or paragraph
	 * 
	 * @param sOriginal
	 * @param iPosNow
	 * @return
	 */
	private static int getNextPositionSentenceEnd(String sOriginal, int iPosNow)
	{
		int iPosSentence = sOriginal.indexOf(SENTENCE_MARKER, iPosNow + 1);
		int iPosParagraph = sOriginal.indexOf(PARAGRAPH_MARKER, iPosNow + 1);
		int iNext = -1;
		if (iPosSentence > -1)
			iNext = iPosSentence + SENTENCE_MARKER.length();
		if (iPosParagraph > -1 && (iNext > iPosParagraph || iNext == -1))
			iNext = iPosParagraph + PARAGRAPH_MARKER.length();
	
		return iNext;
	}

	/**
	 * make function to 
	 * 1. mark paragraphs
	 * 2. mark sentences
	 * 
	 * @param sOriginal
	 * @return
	 */
	protected static String mark(String sStringInput)
	{
		sStringInput = Main_RSVP.fixText(sStringInput);
		sStringInput = fixEnglishDot(sStringInput);
		
		sStringInput = sStringInput.replaceAll("\n\n", 
		                                       "\n\n" + PARAGRAPH_MARKER);
		
		sStringInput = sStringInput.replaceAll("\\. ", 
		                                       "\\. " + SENTENCE_MARKER);

		sStringInput = sStringInput.replaceAll("\\? ", 
		                                       "\\? " + SENTENCE_MARKER);

		sStringInput = sStringInput.replaceAll("\\! ", 
		                                       "\\! " + SENTENCE_MARKER);

		if (!sStringInput.endsWith(PARAGRAPH_MARKER))
			sStringInput += "\n\n" + PARAGRAPH_MARKER;
		
		sStringInput = unfixEnglishDot(sStringInput);
//		System.out.println(sStringInput);
		
		return sStringInput;
	}

	/**
	 * @param sStringInput
	 * @return need to fix string, otherwise it will be considered end of sentence
	 */
	private static String fixEnglishDot(String sStringInput)
	{
		sStringInput = sStringInput.replaceAll("Ms\\.", "_Ms._");
		sStringInput = sStringInput.replaceAll("Mrs\\.", "_Mrs._");
		sStringInput = sStringInput.replaceAll("Mr\\.", "_Mr._");
		sStringInput = sStringInput.replaceAll("L\\.A\\.", "_L.A._");
		sStringInput = sStringInput.replaceAll("No\\.", "_No._");
		
		return sStringInput;
	}

	/**
	 * @param sStringInput
	 * @return need to fix string, otherwise it will be considered end of sentence
	 */
	private static String unfixEnglishDot(String sStringInput)
	{
		sStringInput = sStringInput.replaceAll("_Ms\\._", "Ms.");
		sStringInput = sStringInput.replaceAll("_Mrs\\._", "Mrs.");
		sStringInput = sStringInput.replaceAll("_Mr\\._", "Mr.");
		sStringInput = sStringInput.replaceAll("_L\\.A\\._", "L.A.");
		sStringInput = sStringInput.replaceAll("_No\\._", "No.");
		
		return sStringInput;
	}

	/**
	 * @return
	 */
	public String getInfo()
	{
		StringBuffer sb = new StringBuffer();
		sb.append("(");
		sb.append(isThisSentenceStartingAParagraph()?"P":"S");
		sb.append("-");
		sb.append(!isTranslation ? "O":"T");
		sb.append(" " + iParagraph + "-" + iLineInParagraph);
		sb.append(") ");
		sb.append(sSentenceValue);
		
		return sb.toString();
	}

	/**
	 * 
	 * @return
	 */
	public int getLocation_paragraphNumber()
	{	
		return iParagraph;
	}
	
	/**
	 * @param aCombined
	 * @throws IOException 
	 */
	public static void outputResultFileSentences(ArrayList<Sentence> aCombined, File fOutputFileName) throws IOException
	{
		StringBuffer sb = new StringBuffer();
		for(Sentence s : aCombined) {
			sb.append(s.getInfo());
			sb.append("\n");
		}
		FileUtility.writeToFile(fOutputFileName, sb.toString());	
	}

	/**
	 * Translate all sentences and output to a file
	 * 
	 * @param arSentences
	 * @param fOutput
	 * @throws Exception
	 */
	public static String translateSentences_English_to_Romanian(
													ArrayList<Sentence> arSentences) throws Exception
	{
		final boolean doBlockTranslate = false;
		
		
		String[] arOriginal = new String[arSentences.size()];
		for(int i = 0; i < arSentences.size(); i++) {			
			arOriginal[i] = arSentences.get(i).sSentenceValue;
			if ("".trim().equals(arOriginal[i]))
				arOriginal[i] = "empty";

		}
		
		// use Google translate
		Translate.setHttpReferrer("ro.ClearHarmony.net");

		String[] arTranslated;
		if (doBlockTranslate)
			arTranslated = Translate.execute(arOriginal, Language.ENGLISH, Language.ROMANIAN);		
		
		StringBuffer sb = new StringBuffer();
		for(int i = 0; i < arSentences.size(); i++) {
			Sentence s = arSentences.get(i);

			sb.append(s.getInfo());
			sb.append("\n");
			
			String sTranslated;
			if (doBlockTranslate) {
				sTranslated = fixCommonTranlationMistakes(arTranslated[i]);
			} else {
				System.out.println();
				System.out.println("s.sSentenceValue = " + s.sSentenceValue);
				if ("".equals(s.sSentenceValue))
					s.sSentenceValue = "empty";
				
				sTranslated = Translate.execute(s.sSentenceValue, Language.AUTO_DETECT, Language.ROMANIAN);	
				System.out.println("     sTranslated = " + sTranslated);
			}
			
			Sentence st = new Sentence(s.sSentenceValue + s.sNextSentenceType, s.prev, s.iParagraph, s.iLineInParagraph, true);					
			st.sSentenceValue = sTranslated;

			sb.append(st.getInfo());
			sb.append("\n");			
			sb.append("\n");			
		}
		
		return sb.toString();
	}

	
	/**
	 * @param translation
	 * @return
	 */
	public static String fixCommonTranlationMistakes(String translation)
	{
//		translation = translation.replaceAll("_Ms\\._", "doamna");
//		translation = translation.replaceAll("_Mr\\._", "domnul");
//
//		if (translation.length() > 2) {
//			// make sentence start with upper case
//			translation = translation.substring(0, 1).toUpperCase() + translation.substring(1);
//		}
		
		return translation;
	}

	/**
	 * Output results for each paragraph with paragraph statistics
	 * 
	 * @param arSentences
	 * @param fOutputFileName
	 * @throws IOException
	 */
	public static void outputResultFileParagraphs(
													ArrayList<Sentence> arSentences,
													File fOutputFileName) throws IOException
	{
		StringBuffer sb = new StringBuffer();
		for(Sentence s : arSentences) {
			if (s.isThisSentenceStartingAParagraph()) {
				if (!s.isTranslation) sb.append("\n");
				sb.append("\n" + s.getInfo());
			}
			else
				sb.append(" " + s.sSentenceValue);
			
		}
		FileUtility.writeToFile(fOutputFileName, sb.toString());			
	}
}
